﻿using SuperX.Common;
using SuperX.Common.BasicService;
using SuperX.Common.Collection;
using SuperX.Common.Helper;
using SuperX.Common.Log;
using SuperX.Common.PlugIn;
using SuperX.DataService;
using SuperX.DataService.Abstract;
using SuperX.Helper;
using SuperX.Helper.OS;
using SuperX.Helper.PageBreak;
using SuperX.Helper.ServiceResponse;
using SuperX.Helper.Util;
using SuperX.DeviceService.Model;
using SuperX.TimeManagerService;
using IronPython.Runtime.Operations;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;

namespace SuperX.DeviceService
{
    public class DataManager : BasicObjCollection<IBasicObject>, IDataServer
    {
        /// <summary>
        /// 定时器管理
        /// </summary>
        private TimerManager TimerManager = TimerManager.Instance;

        private IProject _project = BasicServiceManager.GetProjService().Project;
        public Dictionary<string, bool> TagsKey { get; set; } = new Dictionary<string, bool>();

        //授权检查
        private Thread LicenseThread;

        public override string ServiceType
        {
            get => typeof(DataManager).FullName + "," + typeof(DataManager).Assembly.ManifestModule.Name;
            set { }
        }

        private ListObjectCollection<DataManager, IDriver> _DriverGroups;

        public ListObjectCollection<DataManager, IDriver> DriverGroups
        {
            get => _DriverGroups ?? (_DriverGroups = new ListObjectCollection<DataManager, IDriver>(this));
            set
            {
                _DriverGroups = value;
                _DriverGroups.SetParent(this);
            }
        }

        private Dictionary<string, IIOTag> _tagGroups;

        /// <summary>
        /// 设备集成下所有的IOTag的集合
        /// </summary>
        public Dictionary<string, IIOTag> IOTagGroup
        {
            get => _tagGroups ?? (_tagGroups = new Dictionary<string, IIOTag>());
            set
            {
                _tagGroups = value;
            }
        }

        private EasyThread _reConnected;

        public IIOTag IndexFind(long id)
        {
            int index = GetItemProperties(id);
            if (index < 0) return null;
            return NameFind(_list[index].Name);
        }

        public IIOTag NameFind(string name)
        {
            if (string.IsNullOrEmpty(name)) return null;
            IOTagGroup.TryGetValue(name, out var v);
            return v;
        }

        private const int PORT = 6543;

        /// <summary>
        /// 变量List集合
        /// </summary>
        public IList<TagConfig> MetaDataList
        {
            get => _list ?? new List<TagConfig>();
        }

        public IList<Scaling> ScalingList
        {
            get => _scales;
        }

        public object SyncRoot
        {
            get
            {
                if (_syncRoot == null)
                {
                    Interlocked.CompareExchange(ref _syncRoot, new object(), null);
                }
                return _syncRoot;
            }
        }

        public IEnumerable<IDriver> Drivers => _DriverGroups.Values;

        public Dictionary<IPAddress, Socket> SocketList
        {
            get
            {
                return _socketThreadList;
            }
        }

        public DeviceConfig Config { get; set; }

        /// <summary>
        /// 是否完成初始化
        /// </summary>
        public bool IsInit { get; set; }

        public override IBasicObject this[string name] => DriverGroups.Values.FirstOrDefault(g => g.Name == name);

        private readonly string MachineCode;

        private readonly IHostService _server;

        public DataManager(DeviceConfig config, IHostService server)
        {
            Config = config;
            _server = server;
            this.Parent = server;
            this.Name = "DRV";
            MachineCode = Machine.GetMachineCode();
        }

        public void Init()
        {
            _scales = new List<Scaling>();
            _drivers = new SortedList<string, IDriver>();
            _list = new List<TagConfig>();
            _reConnected = new EasyThread(Reconnect, Config.CYCLE);
            _reConnected.Start();
            Initialize();
            InitConnection();
            cpuInit();
            IsInit = true;
        }

        public void Start()
        {
            _socketThreadList = new Dictionary<IPAddress, Socket>();
        }

        private void timer3_Elapsed(object sender, ElapsedEventArgs e)
        {
        }

        private void timer2_Elapsed(object sender, ElapsedEventArgs e)
        {
        }

        /// <summary>
        /// 断线重连检查
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void timer1_Elapsed(object sender, ElapsedEventArgs e)
        {
            foreach (var driver in Drivers)
            {
                if (driver.IsClosed)
                    if (driver.Connect())
                        Logger.Trace($"设备{driver.Name}重连成功！");
            }
        }

        private void Reconnect()
        {
            List<Task> tasks = new List<Task>();
            foreach (var driver in Drivers)
            {
                if (driver.IsClosed)
                {
                    Task task = Task.Factory.StartNew(() =>
                    {
                        if (driver.Connect())
                            Logger.Trace($"设备{driver.Name}重连成功！");
                    });
                    tasks.Add(task);
                }
            }
            Task.WaitAll(tasks.ToArray());
        }

        /// <summary>
        /// 驱动，变量初始化
        /// </summary>
        public void Initialize()
        {
            _mapping = new Dictionary<string, IIOTag>();
            if (Config.DriverGroups == null) return;
            //驱动初始化
            foreach (var item in Config.DriverGroups)
            {
                string assemblyName = Path.Combine(Environment.CurrentDirectory, item.AssemblyName);
                if (!File.Exists(assemblyName))
                    assemblyName = Path.Combine(Environment.CurrentDirectory, "Drivers", item.AssemblyName);
                if (!File.Exists(assemblyName))
                {
                    Logger.Warn($"{item.Name}驱动文件不存在，请检查路径！");
                    continue;
                }
                if (!item.Enabled) continue;
                var driver = AddDriver(item.Name, item.NodeKey, assemblyName, item.ClassFullName, item.Argument);
                if (driver == null)
                {
                    Logger.Warn($"{item.Name}驱动加载失败！请检查驱动配置。");
                    continue;
                }
                driver.ConfigName = item.FullName;
                driver.DriverNO = item.DriverNO;
                //组初始化
                foreach (var groupCfg in item.Groups)
                {
                    var _tagList = new List<TagConfig>();
                    //变量初始化
                    foreach (var tagMeta in groupCfg.TagGroups.Values)
                    {
                        _tagList.Add(tagMeta);
                    }
                    var group = driver.AddGroup(groupCfg.Name, groupCfg.UpdateRate, groupCfg.DeadBand, groupCfg.IsActive);
                    group.ConfigName = groupCfg.FullName;
                    if (group != null)
                        group.AddItems(_tagList);
                }
                if (driver is IVirtualDriver virutalDv)
                {
                    virutalDv.Init();
                }
            }
            GetConfigTags();
            Logger.Info($"初始化变量{IOTagGroup.Count}");
        }

        public Dictionary<string, bool> GetConfigTags()
        {
            List<TagConfig> tags = new List<TagConfig>();
            foreach (var item in Config.DriverGroups)
            {
                var items = item.Groups.Values.SelectMany(a => a.TagGroups.Values);
                tags.AddRange(items);
            }
            foreach (var item in tags)
            {
                TagsKeyAdd(item.FullName, item.Archive);
            }
            Logger.Info($"当前配置变量数：{TagsKey.Count}");
            return TagsKey;
        }

        /// <summary>
        /// 配置的Tag转换成运行的Tag全称,并加入到词典
        /// </summary>
        /// <param name="tagFullName">tag全称</param>
        /// <param name="archive">是否归档</param>
        private void TagsKeyAdd(string tagFullName, bool archive)
        {
            var s = tagFullName;
            if (tagFullName.Contains("."))
            {
                var arrary = tagFullName.split(".");
                arrary[0] = "DRV";
                var key = string.Join(".", arrary);
                TagsKey[key] = archive;
            }
        }

        /// <summary>
        /// 驱动连接初始化
        /// </summary>
        private void InitConnection()
        {
            LoadDriverExternal();
            TaskScheduler.UnobservedTaskException += (s, e) =>
            {
                //设置所有未觉察异常被觉察
                e.SetObserved();
            };
            Task.Factory.StartNew(() => Parallel.ForEach(DriverGroups.Values, s =>
            {
                DriverConnect(s);
            })).Wait(5000);

            //强制垃圾会受到
            GC.Collect();
            //等待终结器处理
            GC.WaitForPendingFinalizers();

            TimerManager.Start();
            LicenseThread.Start();
            Logger.Info($"连接变量数量：{IOTagGroup.Count}");
        }

        private void DriverConnect(IDriver driver)
        {
            try
            {
                if (driver.IsClosed)
                {
                    if (driver.Connect())
                        Logger.Trace($"设备{driver.Name}连接成功！");
                }
                foreach (var group in driver.Groups)
                {
                    //if (!group.IsActive) continue;  //分组不激活不进行值变化事件绑定处理
                    group.DataChange += new DataChangeEventHandler(grp_DataChange);
                    group.IsActive = group.IsActive;
                    foreach (var item in group.Items)
                    {
                        //if(!item.Active) continue;
                        IOTagGroup.Add(item.FullName, item);
                        TimerRegister(item);
                    }
                }
                driver.OnError += new IOErrorEventHandler(reader_OnClose);
            }
            catch (Exception ex)
            {
                Logger.WarnException(ex);
            }
        }

        private void Item_ValueChanged(object sender, TagChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void LoadDriverExternal()
        {
            var regInfos = CheckReg();
            foreach (var driver in DriverGroups.Values)
            {
                if (regInfos == null)
                {
                    driver.ExpiryTime = DateTime.Now.AddHours(2);
                    Logger.Warn($"{driver.Name}：没有可用的授权信息，试用两小时！");
                    continue;
                }
                var driverRegInfo = regInfos.RegBase.DriverRegInfo.Where(d => d.DriverFullName == driver.GetType().FullName).FirstOrDefault();
                if (driverRegInfo != null && driverRegInfo.RegOfNumber > 0)
                {
                    driver.ExpiryTime = Convert.ToDateTime(regInfos.RegBase.ExpiryDate);
                    Logger.Info($"{driver.Name}：驱动授权成功！");
                    if (driver.ExpiryTime < DateTime.Now.AddMonths(1))
                        Logger.Warn($"{driver.Name}：警告！授权期限不足一个月，请尽快与厂商联系！");
                    driverRegInfo.RegOfNumber--;
                }
                else
                {
                    driver.ExpiryTime = DateTime.Now.AddHours(2);
                    Logger.Warn($"{driver.Name}：没有可用的授权信息，试用两小时！");
                }
            }
            LicenseThread = new Thread(License) { IsBackground = true };
        }

        public void License()
        {
            while (true)
            {
                try
                {
                    lock (this)
                    {
                        foreach (var driver in DriverGroups.Values)
                        {
                            if (driver.ExpiryTime < DateTime.Now)
                            {
                                try
                                {
                                    Logger.Info($"驱动授权时间2-{driver.Name}：{driver.ExpiryTime}");
                                    Logger.Info($"现在时间：{DateTime.Now}");
                                    driver.Dispose();
                                }
                                catch (Exception ex)
                                {
                                    Logger.ErrorException(ex);
                                }
                                Logger.Error($"{driver.Name}：授权时间已到期！！！");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorException(ex);
                }
                finally
                {
                    Thread.Sleep(1000 * 60 * 30);
                }
            }
        }

        public RegInfo CheckReg()
        {
            RSACryption rsa = new RSACryption();
            if (!File.Exists(Config.LicenseFilePath))
            {
                Logger.Error("无授权文件！");
                return null;
            }
            var strReg = File.ReadAllText(Config.LicenseFilePath, Encoding.UTF8);
            var infoString = Encoding.UTF8.GetString(Convert.FromBase64String(strReg));
            var reg = JsonHelper.TransferObjectJsonDeserialize<RegInfo>(infoString);
            if (reg == null)
            {
                Logger.Error("无效的授权文件信息！");
                return null;
            }
            else if (rsa.SignatureDeformatter(Config.PublicKey, rsa.GetHash(JsonHelper.TransferObjectJsonSerialize(reg.RegBase, false)), reg.Signature))
            {
                if (!(reg.RegBase.MachineCode == MachineCode))
                {
                    Logger.Error("非当前机器授权信息，请核对！");
                    return null;
                }
                else if (!IsValidity(reg.RegBase.ExpiryDate))
                {
                    Logger.Error("授权时间已过期，请重新注册！");
                    return null;
                }
                else
                    return reg;
            }
            else
            {
                Logger.Error("授权信息验证失败！");
                return null;
            }
        }

        public bool AddDriverCheckLicense(DriverConfig driver)
        {
            if (!driver.Enabled) return true;
            var regInfos = CheckReg();
            if (regInfos != null)
            {
                var driverRegInfo = regInfos.RegBase.DriverRegInfo.Where(d => d.DriverFullName == driver.ClassFullName).FirstOrDefault();
                if (driverRegInfo != null)
                {
                    var CurrentDriverNum = Config.DriverGroups.Values.Where(d => d.ClassFullName == driver.ClassFullName && d.Enabled).ToList().Count;
                    if (CurrentDriverNum < driverRegInfo.RegOfNumber)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public List<BaseTreeNode> GetDefaultDriverConfig()
        {
            List<DriverConfig> driverConfigs = new List<DriverConfig>();
            var regInfos = CheckReg();
            var defDrivercfg = Config.DefaultDriverConfig;
            if (regInfos != null)
            {
                driverConfigs = (from m in defDrivercfg
                                 from s in regInfos.RegBase.DriverRegInfo
                                 where m.ClassFullName == s.DriverFullName
                                 select m).ToList();
            }
            var groups = driverConfigs.GroupBy(d => d.GroupName);
            List<BaseTreeNode> treeNodes = new List<BaseTreeNode>();
            foreach (IGrouping<string, DriverConfig> group in groups)
            {
                var groupNode = new BaseTreeNode
                {
                    Id = group.Key,
                    Name = group.Key,
                    ParentId = "0",
                };
                treeNodes.Add(groupNode);
                var manufacs = group.GroupBy(d => d.Manufacture);
                //品牌分类
                foreach (var manufac in manufacs)
                {
                    var manufacNode = new BaseTreeNode($"{group.Key}.{manufac.Key}", manufac.Key, groupNode);
                    treeNodes.Add(manufacNode);
                    foreach (var item in manufac)
                    {
                        var itemNode = new BaseTreeNode(item.ClassFullName, item.Name, manufacNode);
                        itemNode.AssemblyName = item.AssemblyName;
                        itemNode.ClassFullName = item.ClassFullName;
                        itemNode.PreDriverName = item.PreDriverName;
                        itemNode.Argument = item.Argument;
                        itemNode.AddressExtend = item.AddressExtend;
                        treeNodes.Add(itemNode);
                    }
                }
            }
            var driverTree = TreeHelper.BulidTreeByRecursive(treeNodes, new List<BaseTreeNode>(), "0");
            return driverTree;
        }

        /// <summary>
        /// 是否在有效期内
        /// </summary>
        private bool IsValidity(string validity)
        {
            return DateTime.Now < Convert.ToDateTime(validity);
        }

        /// <summary>
        /// 注册定时器
        /// </summary>
        /// <param name="tag"></param>
        private void TimerRegister(IIOTag tag)
        {
            if (tag.Interval <= 0) return;
            var key = tag.Interval.ToString();
            var timer = TimerManager.GetTimer(key) as TagTimeCase;
            if (timer == null)
            {
                timer = new TagTimeCase(key, tag.Interval);
                timer.Add(tag);
                TimerManager.RegiserTimer(key, timer);
            }
            else
            {
                timer.Add(tag);
            }
        }

        private void grp_DataChange(object sender, DataChangeEventArgs e)
        {
        }

        /// <summary>
        /// 激活变量
        /// </summary>
        /// <param name="active"></param>
        /// <param name="items"></param>
        public void ActiveItem(bool active, params IIOTag[] items)
        {
            Dictionary<IGroup, List<long>> dict = new Dictionary<IGroup, List<long>>();
            for (int i = 0; i < items.Length; i++)
            {
                List<long> list = null;
                var iotag = items[i];
                dict.TryGetValue(iotag.ParentGroup, out list);
                if (list != null)
                {
                    list.Add(iotag.Identity);
                }
                else
                    dict.Add(iotag.ParentGroup, new List<long> { iotag.Identity });
            }
            foreach (var item in dict)
            {
                item.Key.SetActiveState(active, item.Value.ToArray());
            }
        }

        /// <summary>
        /// 加载驱动
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        /// <param name="assembly"></param>
        /// <param name="className"></param>
        /// <param name="argument">参数集合</param>
        /// <returns></returns>
        public IDriver AddDriver(string name, string nodeName, string assembly, string className, Dictionary<string, ArgumentModel> argument)
        {
            var exists = DriverGroups.Values.FirstOrDefault(a => a.Name == name && a.NodeKey == nodeName);
            if (exists != null)
                return exists;
            IDriver dv = null;
            try
            {
                string assemblyName = Path.Combine(Environment.CurrentDirectory, assembly);
                if (!File.Exists(assemblyName))
                    assemblyName = Path.Combine(Environment.CurrentDirectory, "Drivers", assembly);
                if (!File.Exists(assemblyName))
                {
                    Logger.Warn($"{assembly}驱动文件不存在，请检查路径！");
                }
                var ass = Assembly.LoadFrom(assemblyName);
                var dvType = ass.GetType(className);
                if (dvType != null)
                {
                    dv = Activator.CreateInstance(dvType, new object[] { this, name, nodeName }) as IDriver;
                    dv.Name = name;
                    //dv.Parent = this;
                    foreach (var item in argument)
                    {
                        var prop = dvType.GetProperty(item.Key);
                        if (prop != null)
                        {
                            if (prop.PropertyType.IsEnum)
                                prop.SetValue(dv, Enum.Parse(prop.PropertyType, item.Value.Value), null);
                            else if (prop.PropertyType.Equals(typeof(List<FileAnalysisConfig>)))
                                prop.SetValue(dv, Convert.ChangeType(item.Value.FileAnalysis, prop.PropertyType, CultureInfo.CreateSpecificCulture("en-US")), null);
                            else
                                prop.SetValue(dv, Convert.ChangeType(item.Value.Value, prop.PropertyType, CultureInfo.CreateSpecificCulture("en-US")), null);
                        }
                    }
                    DriverGroups.Add(dv);
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"加载驱动失败{ex.Message}");
            }
            return dv;
        }

        /// <summary>
        /// 创建无参实例，用于获取寄存器列表，默认地址等方法用，无法用于创建连接实例
        /// </summary>
        /// <param name="assembly"></param>
        /// <param name="className"></param>
        /// <returns></returns>
        public DriverBase GetDriver(string assembly, string className, Dictionary<string, ArgumentModel> argument)
        {
            DriverBase dv = null;
            try

            {
                string assemblyName = Path.Combine(Environment.CurrentDirectory, assembly);
                if (!File.Exists(assemblyName))
                    assemblyName = Path.Combine(Environment.CurrentDirectory, "Drivers", assembly);
                if (!File.Exists(assemblyName))
                {
                    Logger.Warn($"{assembly}驱动文件不存在，请检查路径！");
                }
                var ass = Assembly.LoadFrom(assemblyName);
                var dvType = ass.GetType(className);
                if (dvType != null)
                {
                    dv = Activator.CreateInstance(dvType) as DriverBase;
                    foreach (var item in argument)
                    {
                        var prop = dvType.GetProperty(item.Key);
                        if (prop != null)
                        {
                            if (prop.PropertyType.IsEnum)
                                prop.SetValue(dv, Enum.Parse(prop.PropertyType, item.Value.Value), null);
                            else if (prop.PropertyType.Equals(typeof(List<FileAnalysisConfig>)))
                                prop.SetValue(dv, Convert.ChangeType(item.Value.FileAnalysis, prop.PropertyType, CultureInfo.CreateSpecificCulture("en-US")), null);
                            else
                                prop.SetValue(dv, Convert.ChangeType(item.Value.Value, prop.PropertyType, CultureInfo.CreateSpecificCulture("en-US")), null);
                        }
                    }
                    return dv;
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorException(ex);
            }
            return null;
        }

        /// <summary>
        /// 卸载驱动
        /// </summary>
        /// <param name="device"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool RemoveDriver(IDriver device)
        {
            lock (SyncRoot)
            {
                if (_drivers.Remove(device.Name))
                {
                    device.Dispose();
                    device = null;
                    return true;
                }
                return false;
            }
        }

        /// <summary>
        /// 添加IOTag项
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool AddItemIndex(string key, IIOTag value)
        {
            key = key.ToUpper();
            if (_mapping.ContainsKey(key))
                return false;
            _mapping.Add(key, value);
            return true;
        }

        /// <summary>
        /// 移除IOTag项
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool RemoveItemIndex(string key)
        {
            return _mapping.Remove(key.ToUpper());
        }

        public int Write(string tagName, object value)
        {
            var objs = BasicServiceManager.GetProjService().Project.Objects;
            if (!BasicServiceManager.GetProjService().Project.Objects.ContainsKey(tagName)) return -1;
            var tag = BasicServiceManager.GetProjService().Project.Objects[tagName] as IIOTag;
            if (tag.ReadWriteMode == ReadWriteMode.ReadOnly) return ErrorCode.WriteNotSupport;
            if (tag == null) return -1;
            int res = -1;
            var device = tag.Parent.Parent as IReaderWriter;
            ///虚拟只读设备的，可以通过API控制写入Tag的值
            if (device is IVirtualDriver virtualDriver)
            {
                tag.UpdateTagValue(value);
                return 0;
            }
            else if (device is IPLCDriver plc || device is IReallDriver real)   //解决雅马哈控制请求文件的问题
            {
                if (tag.TagType == TagType.Exclusive)
                {
                    tag.UpdateTagValue(value);
                    return 0;
                }
                switch (tag.Address.VarType)
                {
                    case DataType.BOOL:
                        {
                            if (value.ToString() == "1") value = true;
                            if (value.ToString() == "0") value = false;
                            var v = bool.Parse(value.ToString());
                            var _IOTag = tag as BoolTag;
                            _IOTag.WriteValue = v;
                            res = device.WriteBit(tag.Address, v);
                            break;
                        }

                    case DataType.STR:
                        {
                            var _IOTag = tag as StringTag;
                            _IOTag.WriteValue = value.ToString();
                            res = device.WriteString(tag.Address, value.ToString());
                            break;
                        }

                    case DataType.BYTE:
                        {
                            var _IOTag = tag as ByteTag;
                            var bytev = byte.Parse(value.ToString());
                            _IOTag.WriteValue = bytev;
                            res = device.WriteBits(tag.Address, bytev);
                            break;
                        }

                    case DataType.SHORT:
                        {
                            var _IOTag = tag as ShortTag;
                            var shortv = Int16.Parse(value.ToString());
                            _IOTag.WriteValue = shortv;
                            res = device.WriteInt16(tag.Address, shortv);
                            break;
                        }

                    case DataType.INT:
                        {
                            var _IOTag = tag as IntTag;
                            var intV = int.Parse(value.ToString());
                            _IOTag.WriteValue = intV;
                            res = device.WriteInt32(tag.Address, intV);
                            break;
                        }

                    case DataType.WORD:
                        {
                            var _IOTag = tag as UShortTag;
                            var wordV = UInt16.Parse(value.ToString());
                            _IOTag.WriteValue = wordV;
                            res = device.WriteUInt16(tag.Address, wordV);
                            break;
                        }

                    case DataType.DWORD:
                        {
                            var _IOTag = tag as UIntTag;
                            var dwordV = UInt32.Parse(value.ToString());
                            _IOTag.WriteValue = dwordV;
                            res = device.WriteUInt32(tag.Address, dwordV);
                            break;
                        }

                    case DataType.FLOAT:
                        {
                            var _IOTag = tag as FloatTag;
                            var floatV = float.Parse(value.ToString());
                            _IOTag.WriteValue = floatV;
                            res = device.WriteFloat(tag.Address, floatV);
                            break;
                        }

                    case DataType.DYNAMIC:
                        {
                            var _IOTag = tag as DynamicTag;
                            _IOTag.WriteValue = value;
                            res = device.WriteDynamic(tag, value);
                            break;
                        }
                }
            }
            if (res == 0)
            {
                tag.WriteQuality = QUALITIES.OK;
            }
            else
            {
                tag.WriteQuality = QUALITIES.NG;
            }
            return res;
        }

        /// <summary>
        /// 变量浏览
        /// </summary>
        /// <param name="browseType"></param>
        /// <param name="tagName"></param>
        /// <param name="dataType"></param>
        /// <returns></returns>
        public IEnumerable<string> BrowseItems(BrowseType browseType, string tagName, DataType dataType)
        {
            lock (SyncRoot)
            {
                if (_list.Count == 0) yield break;
                int len = _list.Count;
                if (itemList == null)
                {
                    itemList = new string[len];
                    for (int i = 0; i < len; i++)
                    {
                        itemList[i] = _list[i].Name;
                    }
                    Array.Sort(itemList);
                }
                int ii = 0;
                bool hasTag = !string.IsNullOrEmpty(tagName);
                bool first = true;
                string str = hasTag ? tagName + SPLITCHAR : string.Empty;
                if (hasTag)
                {
                    ii = Array.BinarySearch(itemList, tagName);
                    if (ii < 0) first = false;
                    //int strLen = str.Length;
                    ii = Array.BinarySearch(itemList, str);
                    if (ii < 0) ii = ~ii;
                }
                //while (++i < len && temp.Length >= strLen && temp.Substring(0, strLen) == str)
                do
                {
                    if (first && hasTag)
                    {
                        first = false;
                        yield return tagName;
                    }
                    string temp = itemList[ii];
                    if (hasTag && !temp.StartsWith(str, StringComparison.Ordinal))
                        break;
                    if (_mapping[temp].Address.VarType == dataType)
                    {
                        bool b3 = true;
                        if (browseType != BrowseType.Flat)
                        {
                            string curr = temp + SPLITCHAR;
                            int index = Array.BinarySearch(itemList, ii, len - ii, curr);
                            if (index < 0) index = ~index;
                            b3 = itemList[index].StartsWith(curr, StringComparison.Ordinal);
                            if (browseType == BrowseType.Leaf)
                                b3 = !b3;
                        }
                        if (b3)
                            yield return temp;
                    }
                } while (++ii < len);
            }
        }

        public override void Dispose()
        {
            lock (this)
            {
                try
                {
                    if (timer1 != null)
                        timer1.Dispose();
                    if (timer2 != null)
                        timer2.Dispose();
                    if (timer3 != null)
                        timer3.Dispose();
                    if (_drivers != null)
                    {
                        foreach (var driver in Drivers)
                        {
                            driver.OnError -= this.reader_OnClose;
                            driver.Dispose();
                        }
                    }
                    foreach (var socket in _socketThreadList.Values)
                    {
                        socket.Dispose();
                    }
                    _mapping.Clear();
                    TimerManager.Stop();
                }
                catch (Exception e)
                {
                    Logger.Error($"销毁失败：{e.Message}");
                }
            }
            base.Dispose();
        }

        private void reader_OnClose(object sender, IOErrorEventArgs e)
        {
            Logger.Error($"驱动注销失败：{e.Reason}");
        }

        /// <summary>
        /// 通过组名获取组信息
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public IGroup GetGroupByName(string name)
        {
            if (string.IsNullOrEmpty(name)) return null;
            foreach (var device in Drivers)
            {
                foreach (var group in device.Groups)
                {
                    if (group.Name == name) return group;
                }
            }
            return null;
        }

        public int GetItemProperties(long id)
        {
            return 0;
        }

        public int GetScaleByID(long id)
        {
            if (_scales == null || _scales.Count == 0) return -1;
            return _scales.BinarySearch(new Scaling { ID = id });
        }

        public PageResult<TagConfig> GetGroupInfo(TagQueryInputDto input)
        {
            //TODO:获取TagMetaData
            //var TagMetaData = _list.Where(a => a.GroupID == groupId).ToList();

            var device = _project.Objects[input.DriverKey] as DriverConfig;
            if (device == null) return null;
            var group = _project.Objects[input.GroupKey] as GroupConfig;
            var tagConfig = group.TagGroups.Values;
            if (device != null && group != null)
            {
                tagConfig = !string.IsNullOrEmpty(input.SearchValue)
                    ? tagConfig
                    .Where(a =>
                    (!string.IsNullOrEmpty(a.Name) && a.Name.Contains(input.SearchValue)) ||
                    (!string.IsNullOrEmpty(a.Address) && a.Address.Contains(input.SearchValue)) ||
                    (!string.IsNullOrEmpty(a.Description) && a.Description.Contains(input.SearchValue)))
                    .ToList() : tagConfig;
                PageResult<TagConfig> res = new PageResult<TagConfig>()
                {
                    PageNo = input.PageNO,
                    PageSize = input.PageSize,
                    TotalPage = input.TotalPage,
                    TotalRows = input.TotalRows,
                    Rows = tagConfig,
                };
                return DataPaging.SplitList(res);
            }
            return null;
        }

        public PageResult<RunTimeTagModel> GetRunTimeTagInfo(TagQueryInputDto input)
        {
            List<RunTimeTagModel> tags = new List<RunTimeTagModel>();
            if (_project.Objects.ContainsKey(input.DriverKey))
            {
                var a = _project.Objects[input.DriverKey];
            }
            var device = _project.Objects[input.DriverKey] as IDriver;
            var dv = device as DriverBase;
            if (string.IsNullOrEmpty(input.GroupKey) || string.IsNullOrEmpty(input.DriverKey)) return new PageResult<RunTimeTagModel>()
            {
                PageNo = input.PageNO,
                PageSize = input.PageSize,
                TotalPage = input.TotalPage,
                TotalRows = input.TotalRows,
                Rows = tags,
            };
            var group = _project.Objects[input.GroupKey] as IGroup;
            foreach (IIOTag item in group.GetValues())
            {
                tags.Add(new RunTimeTagModel
                {
                    Name = item.Name,
                    FullName = item.FullName,
                    DataType = item.Address.VarType,
                    Address = item.Address.Addr,
                    QualityStamp = item.Quality.ToString(),
                    Value = item.Value,
                    Timestamp = item.TimeStamp,
                    Description = item.Description,
                    WriteValue = item.WriteValue,
                    WriteQuality = item.WriteQuality.ToString(),
                    Unit = item.Unit,
                });
            }
            tags = !string.IsNullOrEmpty(input.SearchValue)
                ? tags
                .Where(a => (a.Name != null && a.Name.Contains(input.SearchValue)) || (a.Address != null && a.Address.Contains(input.SearchValue)) || (a.Description != null && a.Description.Contains(input.SearchValue)))
                .ToList() : tags;
            PageResult<RunTimeTagModel> res = new PageResult<RunTimeTagModel>()
            {
                PageNo = input.PageNO,
                PageSize = input.PageSize,
                TotalPage = input.TotalPage,
                TotalRows = input.TotalRows,
                Rows = tags,
            };
            return DataPaging.SplitList<RunTimeTagModel>(res);
        }

        internal bool BatchAddTag(GroupConfig group, TagConfig tagobj, int quantity, out string message)
        {
            message = string.Empty;
            if (group.TagGroups.Keys.Contains(tagobj.Name))
            {
                message = $"添加失败！该分组已有 {tagobj.Name} 存在！";
                return false;
            }
            group.TagGroups.Add(tagobj);
            var tagNames = GetTagNames(group, tagobj.Name, quantity - 1);
            foreach (var tagName in tagNames)
            {
                var tag = tagobj.DeepCopy<TagConfig>();
                tag.Name = tagName;
                group.TagGroups.Add(tag);
            }
            return true;
        }

        public List<string> GetTagNames(GroupConfig group, string tagName, int quantity)
        {
            var result = new List<string>();
            var i = 0;

            while (result.Count < quantity)
            {
                i++;
                var name = tagName + i.ToString();
                if (!group.TagGroups.Keys.Contains(name)) result.Add(name);
            }
            return result;
        }

        public IOTState GetIOTState()
        {
            try
            {
                return new IOTState
                {
                    ProjectName = _project.Name,
                    ProjectStartUp = _project.StartTime,
                    ProjectRunTime = ((DateTime.Now - _project.StartTime).Ticks / TimeSpan.TicksPerMillisecond).ToString(),
                    DriverAuthCount = CheckReg() == null ? 0 : CheckReg().RegBase.DriverRegInfo.Select(a => a.RegOfNumber).Sum(),
                    DevicesNumber = DriverGroups.Values.Count(),
                    DevicesOnline = DriverGroups.Values.Where(x => x.IsClosed == false).Count(),
                    DevicesOffline = DriverGroups.Values.Where(x => x.IsClosed == true).Count(),
                    TagNumber = IOTagGroup.Count()
                };
            }
            catch (Exception ex)
            {
                Logger.Warn($"获取工程信息失败：{ex.Message}");
            }
            return new IOTState();
        }

        // 获取CPU核心数量
        private int coreCount = Environment.ProcessorCount;

        // 创建PerformanceCounter数组来监测每个核心的使用率
        private PerformanceCounter[] cpuCounters;

        /// <summary>
        /// cpu参数胡初始化
        /// </summary>
        private void cpuInit()
        {
#if !NETSTANDARD2_0
            cpuCounters = new PerformanceCounter[coreCount];
            for (int i = 0; i < coreCount; i++)
            {
                // 创建每个核心的PerformanceCounter对象
                cpuCounters[i] = new PerformanceCounter("Processor", "% Processor Time", i.ToString());
            }
#endif
        }

        public string GetCurrentCPU()
        {
#if !NETSTANDARD2_0
            // 存储每个核心的使用率
            float[] cpuUsages = new float[coreCount];
            // 获取每个核心的使用率
            for (int i = 0; i < coreCount; i++)
            {
                cpuUsages[i] = cpuCounters[i].NextValue();
            }

            // 计算平均使用率
            float averageCpuUsage = 0;
            for (int i = 0; i < coreCount; i++)
            {
                averageCpuUsage += cpuUsages[i];
            }
            averageCpuUsage /= coreCount;
            return averageCpuUsage.ToString();
#else
            var res = LinuxCommand.Bash("top -bn1 | grep 'Cpu'");
            Logger.Info($"-----cpu res {res}");
            var array = res.Split(',');
            var cpustr = array[3];
            var tmp = cpustr.Split(' ');
            return tmp[1];
#endif
        }

        public string GetCurrentMemory()
        {
            //PerformanceCounter theMemCounter = new PerformanceCounter("Process", "Working Set - Private", Process.GetCurrentProcess().ProcessName);
            //return (theMemCounter.NextValue() / 1048576f).ToString("F1");
#if !NETSTANDARD2_0
            var name = Process.GetCurrentProcess().ProcessName;
#else
            var name = "IoTServiceCore";
#endif
            var os = SuperX.Common.OS.OSCommand.GetNewOSCommand();
            var memory = os.GetMemory(name).ToString();
            return memory;
        }

        //private void ReceiveWorkThread(object obj)
        //{
        //    Socket s_Receive = (Socket)obj;
        //    IPAddress addr = null;
        //    try
        //    {
        //        addr = (s_Receive.RemoteEndPoint as IPEndPoint).Address;
        //    }
        //    catch (Exception err)
        //    {
        //        Logger.ErrorException(err);
        //        return;
        //    }
        //    byte[] buffer = new byte[s_Receive.ReceiveBufferSize];     // 创建接收缓冲
        //    while (true)
        //    {
        //        try
        //        {
        //            if (addr == null || !_socketThreadList.ContainsKey(addr)) return;
        //            /*if (!s_Receive.Connected) return;
        //            关于数据传输协议：命令可分为：订单指令（订单类型，增删改标记可各用一个字段，路径ID用GUID，路径状态包括暂停、继续
        //            、终止、启动）；可返回客户端一个可行的路径设备链、ERP交换数据指令（包含DATASET)，冗余切换指令等）
        //             */
        //            int ReceiveCount = s_Receive.Receive(buffer);

        //            if (buffer[0] == FCTCOMMAND.fctHead)
        //            {
        //                //buffer[0]是协议头，1是指令号，2是读方式（缓存还是设备），3、4是ID，5是长度，后接变量值
        //                byte command = buffer[1];
        //                switch (command)
        //                {
        //                    case FCTCOMMAND.fctReadSingle:
        //                        {
        //                            //DataSource source = buffer[2] == 0 ? DataSource.Cache : DataSource.Device;
        //                            short id = BitConverter.ToInt16(buffer, 3);
        //                            byte length = buffer[5];
        //                            byte[] send = new byte[5 + length];
        //                            for (int i = 0; i < 5; i++)
        //                            {
        //                                send[i] = buffer[i];
        //                            }
        //                            IOTag tag = IndexFind(id);
        //                            if (tag != null)
        //                            {
        //                                Storage value = buffer[2] == 0 ? tag.Value : tag.Read(DataSource.Device);
        //                                byte[] bt = tag.ToByteArray(value);
        //                                for (int k = 0; k < bt.Length; k++)
        //                                {
        //                                    send[5 + k] = bt[k];
        //                                }
        //                            }
        //                            else
        //                            {
        //                                //出错处理,可考虑返回一个DATATYPE.NONE类型
        //                            }
        //                            s_Receive.Send(send);
        //                        }
        //                        break;

        //                    case FCTCOMMAND.fctReadMultiple:
        //                        {
        //                            //buffer[0]是协议头，1是指令号，2是读方式（缓存还是设备），3、4是变量数，后接变量值
        //                            //DataSource source = buffer[2] == 0 ? DataSource.Cache : DataSource.Device;
        //                            byte[] send = new byte[s_Receive.SendBufferSize];
        //                            send[0] = FCTCOMMAND.fctHead;
        //                            short count = BitConverter.ToInt16(buffer, 3);//要读取的变量数
        //                            int j = 5; int l = 5;
        //                            if (buffer[2] == 0)
        //                            {
        //                                for (int i = 0; i < count; i++)
        //                                {
        //                                    short id = BitConverter.ToInt16(buffer, l);
        //                                    send[j++] = buffer[l++];
        //                                    send[j++] = buffer[l++];
        //                                    IOTag tag = IndexFind(id);
        //                                    if (tag != null)
        //                                    {
        //                                        byte[] bt = tag.ToByteArray();
        //                                        var length = (byte)bt.Length;
        //                                        send[j++] = length;
        //                                        for (int k = 0; k < length; k++)
        //                                        {
        //                                            send[j + k] = bt[k];
        //                                        }
        //                                        j += length;
        //                                    }
        //                                    else
        //                                    {//类型后跟长度
        //                                        send[j++] = 0;
        //                                    }
        //                                }
        //                            }
        //                            else
        //                            {
        //                                Dictionary<IGroup, List<IOTag>> dict = new Dictionary<IGroup, List<IOTag>>();
        //                                for (int i = 0; i < count; i++)
        //                                {
        //                                    short id = BitConverter.ToInt16(buffer, l);
        //                                    l += 2;
        //                                    IOTag tag = IndexFind(id);
        //                                    if (tag != null)
        //                                    {
        //                                        IGroup grp = tag.ParentGroup;
        //                                        if (!dict.ContainsKey(grp))
        //                                            dict.Add(grp, new List<IOTag> { tag });
        //                                        else
        //                                            dict[grp].Add(tag);
        //                                    }
        //                                }
        //                                foreach (var dev in dict)
        //                                {
        //                                    var list = dev.Value;
        //                                    var array = dev.Key.BatchRead(DataSource.Device, true, list.ToArray());
        //                                    if (array == null) continue;
        //                                    for (int i = 0; i < list.Count; i++)
        //                                    {
        //                                        byte[] bt = list[i].ToByteArray(array[i].Value);
        //                                        var length = (byte)bt.Length;
        //                                        send[j++] = length;
        //                                        for (int k = 0; k < bt.Length; k++)
        //                                        {
        //                                            send[j + k] = bt[k];
        //                                        }
        //                                        j += length;
        //                                    }
        //                                }
        //                            }
        //                            s_Receive.Send(send, 0, j, SocketFlags.None);
        //                        }
        //                        break;

        //                    case FCTCOMMAND.fctWriteSingle:
        //                        {
        //                            //buffer[0]是协议头，1是指令号，2是写方式（缓存还是设备），3、4是ID，5是长度
        //                            short id = BitConverter.ToInt16(buffer, 3);
        //                            byte rs = 0;
        //                            IOTag tag = IndexFind(id);
        //                            if (tag != null)//此处应考虑万一写失败，是否需要更新值
        //                            {
        //                                if (tag.Address.VarType == DataType.STR)
        //                                {
        //                                    StringTag strTag = tag as StringTag;
        //                                    if (strTag != null)
        //                                    {
        //                                        string txt = Encoding.ASCII.GetString(buffer, 6, buffer[5]).Trim((char)0);
        //                                        rs = (byte)tag.Write(txt);
        //                                        if (rs == 0)
        //                                            strTag.String = txt;
        //                                    }
        //                                }
        //                                else
        //                                {
        //                                    Storage value = Storage.Empty;
        //                                    switch (tag.Address.VarType)
        //                                    {
        //                                        case DataType.BOOL:
        //                                            value.Boolean = BitConverter.ToBoolean(buffer, 6);
        //                                            break;

        //                                        case DataType.BYTE:
        //                                            value.Byte = buffer[6];
        //                                            break;

        //                                        case DataType.WORD:
        //                                            value.Word = BitConverter.ToUInt16(buffer, 6);
        //                                            break;

        //                                        case DataType.SHORT:
        //                                            value.Int16 = BitConverter.ToInt16(buffer, 6);
        //                                            break;

        //                                        case DataType.DWORD:
        //                                            value.DWord = BitConverter.ToUInt32(buffer, 6);
        //                                            break;

        //                                        case DataType.INT:
        //                                            value.Int32 = BitConverter.ToInt32(buffer, 6);
        //                                            break;

        //                                        case DataType.FLOAT:
        //                                            value.Single = BitConverter.ToSingle(buffer, 6);
        //                                            break;

        //                                        default:
        //                                            break;
        //                                    }
        //                                    rs = (byte)tag.Write(value, false);
        //                                }
        //                            }
        //                            else
        //                            {
        //                                rs = 0xFF;//此处长度应注意;如无此变量，应返回一个错误代码
        //                            }
        //                            s_Receive.Send(new byte[] { FCTCOMMAND.fctWriteSingle, rs }, 0, 2, SocketFlags.None);//应返回一个错误代码;
        //                        }
        //                        break;

        //                    case FCTCOMMAND.fctWriteMultiple:
        //                        {  //int BatchWrite(IDictionary<ITag, object> items, bool isSync = true);
        //                            int count = BitConverter.ToInt16(buffer, 2);
        //                            int j = 4; byte rs = 0;
        //                            Dictionary<IGroup, SortedDictionary<IOTag, object>> dict = new Dictionary<IGroup, SortedDictionary<IOTag, object>>();
        //                            for (int i = 0; i < count; i++)
        //                            {
        //                                short id = BitConverter.ToInt16(buffer, j);
        //                                j += 2;
        //                                byte length = buffer[j++];
        //                                IOTag tag = IndexFind(id);
        //                                IGroup grp = tag.ParentGroup;
        //                                SortedDictionary<IOTag, object> values;
        //                                if (!dict.ContainsKey(grp))
        //                                {
        //                                    values = new SortedDictionary<IOTag, object>();
        //                                    dict.Add(grp, values);
        //                                }
        //                                else
        //                                    values = dict[grp];
        //                                if (tag != null)
        //                                {
        //                                    switch (tag.Address.VarType)
        //                                    {
        //                                        case DataType.BOOL:
        //                                            values.Add(tag, BitConverter.ToBoolean(buffer, j));
        //                                            break;

        //                                        case DataType.BYTE:
        //                                            values.Add(tag, buffer[j]);
        //                                            break;

        //                                        case DataType.WORD:
        //                                            values.Add(tag, BitConverter.ToUInt16(buffer, j));
        //                                            break;

        //                                        case DataType.SHORT:
        //                                            values.Add(tag, BitConverter.ToInt16(buffer, j));
        //                                            break;

        //                                        case DataType.DWORD:
        //                                            values.Add(tag, BitConverter.ToUInt32(buffer, j));
        //                                            break;

        //                                        case DataType.INT:
        //                                            values.Add(tag, BitConverter.ToInt32(buffer, j));
        //                                            break;

        //                                        case DataType.FLOAT:
        //                                            values.Add(tag, BitConverter.ToSingle(buffer, j));
        //                                            break;

        //                                        case DataType.STR:
        //                                            values.Add(tag, Encoding.ASCII.GetString(buffer, j, length).Trim((char)0));
        //                                            break;
        //                                    }
        //                                }
        //                                j += length;
        //                            }
        //                            foreach (var dev in dict)
        //                            {
        //                                if (dev.Key.BatchWrite(dev.Value) < 0) rs = 0xFF;
        //                            }
        //                            s_Receive.Send(new byte[] { FCTCOMMAND.fctWriteMultiple, rs }, 0, 2, SocketFlags.None);
        //                        }
        //                        break;

        //                    case FCTCOMMAND.fctAlarmRequest://刷新报警数据
        //                        break;

        //                    case FCTCOMMAND.fctReset://重置连接
        //                        {
        //                            byte[] iparry = new byte[4];
        //                            Array.Copy(buffer, 2, iparry, 0, 4);
        //                            IPAddress ipaddr = new IPAddress(iparry);
        //                            if (_socketThreadList.Count > 0 && _socketThreadList.ContainsKey(ipaddr))
        //                            {
        //                                var scok = _socketThreadList[ipaddr];
        //                                _socketThreadList.Remove(ipaddr);
        //                                if (scok != null)
        //                                {
        //                                    scok.Dispose();
        //                                }
        //                            }
        //                        }
        //                        break;

        //                    case FCTCOMMAND.fctHdaRequest:
        //                        {
        //                            DateTime start = DateTime.FromFileTime(BitConverter.ToInt64(buffer, 2));
        //                            DateTime end = DateTime.FromFileTime(BitConverter.ToInt64(buffer, 10));
        //                            try
        //                            {
        //                                //SendHData(GetHData(start, end), new byte[Config.HDALEN], s_Receive);
        //                            }
        //                            catch (Exception err)
        //                            {
        //                                Logger.WarnException(err);
        //                            }
        //                            s_Receive.Send(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        //                            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 24, SocketFlags.None);
        //                        }
        //                        break;

        //                    case FCTCOMMAND.fctHdaIdRequest://优先读取本地HDA文件夹下的二进制归档文件
        //                        {
        //                            DateTime start = DateTime.FromFileTime(BitConverter.ToInt64(buffer, 2));
        //                            DateTime end = DateTime.FromFileTime(BitConverter.ToInt64(buffer, 10));
        //                            short ID = BitConverter.ToInt16(buffer, 18);
        //                            try
        //                            {
        //                                //SendHData(GetHData(start, end, ID), new byte[Config.HDALEN], s_Receive, this[ID]);
        //                            }
        //                            catch (Exception err)
        //                            {
        //                                Logger.WarnException(err);
        //                            }
        //                            s_Receive.Send(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        //                            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 24, SocketFlags.None);
        //                        }
        //                        break;
        //                }
        //            }
        //        }
        //        catch (SocketException ex)
        //        {
        //            var err = ex.SocketErrorCode;
        //            if (err == SocketError.ConnectionAborted || err == SocketError.HostDown || err == SocketError.NetworkDown || err == SocketError.Shutdown || err == SocketError.ConnectionReset)
        //            {
        //                s_Receive.Dispose();
        //                if (addr != null)
        //                    _socketThreadList.Remove(addr);
        //                //s_Receive.Dispose();
        //            }
        //            Logger.WarnException(ex);
        //        }
        //        catch (Exception ex)
        //        {
        //            Logger.WarnException(ex);
        //        }
        //    }
        //}

        public string FileImport(DriverConfig device, string FileName)
        {
            var ds = Helper.NOPI.ExcelHelperForCs.ImportFromExcel(FileName);
            foreach (DataTable tb in ds.Tables)
            {
                if (!device.Groups.Keys.Contains(tb.TableName)) return $"未找到：({device.Name}) 下的 ({tb.TableName}) 分组，请检查配置！";
                var group = device.Groups[tb.TableName];
                var list = Helper.NOPI.ListTableTools.TableToList<TagConfig>(tb, out StringBuilder msg, "FullName,Parent,Identity");
                if (msg.ToString() != "") return msg.ToString();
                var sysTags = group.TagGroups.Values.Where(t => t.TagType != TagType.System).ToList();
                foreach (var sysTag in sysTags)
                {
                    group.TagGroups.Remove(sysTag);
                }
                foreach (var tagConfig in list)
                {
                    if (tagConfig.TagType == TagType.System) continue;
                    if (string.IsNullOrEmpty(tagConfig.Name)) return $"分组：({group.Name}) 下的 (第{list.IndexOf(tagConfig) + 2}行) 内容有误请检查配置！";
                    var tagconfig = group.TagGroups[tagConfig.Name];
                    if (tagconfig != null) group.TagGroups.Remove(tagconfig);
                    group.TagGroups.Add(tagConfig);
                }
            }
            return "";
        }

        #region BasicObjCollection

        public override List<string> GetKeys()
        {
            return _DriverGroups.Values.Select(a => a.Name).ToList();
        }

        public override List<IBasicObject> GetValues()
        {
            var group = DriverGroups.Values.OfType<IBasicObject>().ToList();
            return group;
        }

        public override bool IsUniqueName(string name, IObjCollection parent)
        {
            if (parent != null)
                return parent.IsUniqueName(name, null);
            return true;
        }

        #endregion BasicObjCollection

        #region 历史数据归档查询

        internal bool Stop()
        {
            if (Drivers.Any())
            {
                try
                {
                    foreach (var driver in Drivers)
                    {
                        driver.Dispose();
                    }
                }
                catch (Exception ex)
                {
                    Logger.Warn($"设备断开连接报错,{ex.Message}");
                }
            }
            _reConnected?.Stop();
            Logger.Warn($"设备断开连接完成");
            return true;
        }

        #endregion 历史数据归档查询

        public ApiResponse<TagRecordOutDto> GetTagsValue(List<string> tagFullNames)
        {
            ApiResponse<TagRecordOutDto> res = new ApiResponse<TagRecordOutDto>();
            TagRecordOutDto data = new TagRecordOutDto();
            List<List<object[]>> values = new List<List<object[]>>();
            foreach (string item in tagFullNames)
            {
                if (!_project.Objects.ContainsKey(item)) continue;
                var tag = _project.Objects[item] as IIOTag;
                if (tag.Address.VarType == DataType.BOOL || tag.Address.VarType == DataType.STR) continue;
                data.Columns.Add(tag.FullName);
                var array = new object[1] { tag.Value };
                values.Add(new List<object[]> { array });
            }
            data.Times.Add(DateTime.Now);
            data.Values = values;
            res.Data = data;
            return res;
        }

        /// <summary>
        /// 获取多个Tag值
        /// </summary>
        /// <param name="tagFullNames"></param>
        /// <returns></returns>
        public ApiResponse<List<BaseTagOutput>> GetBatchTagValue(List<string> tagFullNames)
        {
            ApiResponse<List<BaseTagOutput>> res = new ApiResponse<List<BaseTagOutput>>();
            List<BaseTagOutput> datas = new List<BaseTagOutput>();
            foreach (string item in tagFullNames)
            {
                if (!_project.Objects.ContainsKey(item)) continue;
                var tag = _project.Objects[item] as IIOTag;
                datas.Add(new BaseTagOutput
                {
                    FullName = tag.FullName,
                    Name = tag.Name,
                    TimeStamp = tag.TimeStamp,
                    QUALITIES = tag.Quality,
                    Value = tag.Value,
                });
            }
            res.Data = datas;
            return res;
        }

        public ApiResponse<string> AddDriver(DriverConfig driver)
        {
            var Drivers = Config.DriverGroups;
            //检查驱动授权信息
            if (!AddDriverCheckLicense(driver))
                return ApiResponse<string>.Fail("没有可用的授权信息，新增失败！");
            Helper.Validation.ValidationMain.ScanIsValid(driver);
            var driverBase = GetDriver(driver.AssemblyName, driver.ClassFullName, driver.Argument);
            var systemGroup = driverBase.GetSystemGroup();
            driver.Groups.Add(systemGroup);
            driverBase.GetDefaultConfig(driver);
            foreach (var item in driver.Argument.Values)
            {
                item.ValueSync = true;
            }
            var deviceType = driver.ClassFullName.Split('.').LastOrDefault();
            if (JudgeExistDevice(driver))
                driver.Name = Config.GetNewDeviceName(deviceType);
            Config.DriverGroups.Add(driver);
            return ApiResponse<string>.Success("新增成功！");
        }

        public void UpdateDriver(DriverConfig driver)
        {
            //检查驱动授权信息
            if (!AddDriverCheckLicense(driver)) return;
            Helper.Validation.ValidationMain.ScanIsValid(driver);
            var driverBase = GetDriver(driver.AssemblyName, driver.ClassFullName, driver.Argument);
            var systemGroup = driverBase.GetSystemGroup();
            driver.Groups.Add(systemGroup);
            driverBase.GetDefaultConfig(driver);
            foreach (var item in driver.Groups.Values)
            {
                var group = _project.Objects[item.FullName] as GroupConfig;
                group.TagGroups = item.TagGroups;
            }
        }

        public ApiResponse<List<TreeModel>> GetTree(string deviceFullName)
        {
            ApiResponse<List<TreeModel>> res = new ApiResponse<List<TreeModel>>();
            if (!_project.Objects.ContainsKey(deviceFullName)) return ApiResponse<List<TreeModel>>.Fail("无法找到设备");
            var config = _project.Objects[deviceFullName] as DriverConfig;
            var dv = GetDriver(config.AssemblyName, config.ClassFullName, config.Argument);
            res.Data = dv.GetTrees();
            return res;
        }

        public ApiResponse<List<GridItem>> GetGrid(string deviceFullName, string parentNode)
        {
            ApiResponse<List<GridItem>> res = new ApiResponse<List<GridItem>>();

            if (!_project.Objects.ContainsKey(deviceFullName)) return ApiResponse<List<GridItem>>.Fail("无法找到设备");
            var config = _project.Objects[deviceFullName] as DriverConfig;
            var dv = GetDriver(config.AssemblyName, config.ClassFullName, config.Argument);
            res.Data = dv.GetGrids(parentNode);
            return res;
        }

        public ApiResponse<List<RunTimeTagModel>> GetEquipmentRuntimeData(string AssetCode)
        {
            var device = DriverGroups.Values.FirstOrDefault(a => a.DriverNO == AssetCode);
            if (device == null) return ApiResponse<List<RunTimeTagModel>>.DeviceNotFound(ErrorMessage.DeviceNotFound);
            List<RunTimeTagModel> res = new List<RunTimeTagModel>();
            var groups = device.Groups;
            foreach (var g in groups)
            {
                foreach (IIOTag item in g.Items)
                {
                    res.Add(new RunTimeTagModel
                    {
                        Name = item.Name,
                        FullName = item.FullName,
                        DataType = item.Address.VarType,
                        Address = item.Address.Addr,
                        QualityStamp = item.Quality.ToString(),
                        Value = item.Value,
                        Timestamp = item.TimeStamp,
                        Description = item.Description,
                        Unit = item.Unit,
                    });
                }
            }
            return ApiResponse<List<RunTimeTagModel>>.Success("获取设备实时参数成功", res);
        }

        public ApiResponse<IDriver> GetRuntimeDriver(string AssetCode)
        {
            var device = DriverGroups.Values.FirstOrDefault(a => a.DriverNO == AssetCode);
            if (device == null) return ApiResponse<IDriver>.DeviceNotFound(ErrorMessage.DeviceNotFound);
            return device.ToResponse();
        }

        private bool JudgeExistDevice(DriverConfig driver)
        {
            var exists = Config.DriverGroups.Values.FirstOrDefault(a => a.NodeKey == driver.NodeKey && a.Name == driver.Name);
            return exists != null;
        }

        private List<TagConfig> _list;
        private Dictionary<string, IIOTag> _mapping;
        private List<Scaling> _scales;
        private object _syncRoot;
        private SortedList<string, IDriver> _drivers = new SortedList<string, IDriver>();
        private List<DriverArgumet> _arguments = new List<DriverArgumet>();
        private string[] itemList = null;
        private const char SPLITCHAR = '.';
        private System.Timers.Timer timer1 = new System.Timers.Timer();
        private System.Timers.Timer timer2 = new System.Timers.Timer();
        private System.Timers.Timer timer3 = new System.Timers.Timer();
        private DateTime _hdastart = DateTime.Now;
        private Dictionary<IPAddress, Socket> _socketThreadList;
        private Dictionary<string, ArchiveTime> _archiveTimes = new Dictionary<string, ArchiveTime>();
    }

    internal struct CpuTime
    {
        public long User;
        public long Nice;
        public long System;
        public long Idle;
        public long Iowait;
        public long Irq;
        public long Softirq;
        public long Steal;
        public long Guest;
        public long GuestNice;

        public long Total => User + Nice + System + Idle + Iowait + Irq + Softirq + Steal + Guest + GuestNice;
        public long Used => User + Nice + System + Irq + Softirq + Steal + Guest + GuestNice;
    }
}